package com.tianji.learning.service.impl;

import cn.hutool.db.DbRuntimeException;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.trade.TradeClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.exceptions.DbException;
import com.tianji.common.utils.*;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.tianji.learning.service.IInteractionReplyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author 
 * @since 2024-12-19
 */
@Service
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {

    @Autowired
    private TradeClient tradeClient;

    /**
     * 新增提问
     * @param questionDTO
     */
    @Override
    public void saveQuestion(QuestionFormDTO questionDTO) {
        // 1.获取登录用户
        Long userId = UserContext.getUser();
        // 2.数据转换
        InteractionQuestion question = BeanUtils.toBean(questionDTO, InteractionQuestion.class);
        // 3.补充数据
        question.setUserId(userId);
        // 4.保存问题
        save(question);
    }


    /**
     * 修改问题
     * @param id
     * @param dto
     */
    @Override
    public void updateQuestion(Long id, QuestionFormDTO dto) {
        //根据课程id修改数据
        InteractionQuestion question = BeanUtils.toBean(dto, InteractionQuestion.class);
        question.setId(id);
        this.updateById(question);
    }


    @Autowired
    private UserClient userClient;

    @Autowired
    @Lazy
    private IInteractionReplyService replyService;
    /**
     * 用户端问题分页查询，
     * @param query
     * @return
     */
    @Override
    public PageDTO<QuestionVO> queryQuestionPage(QuestionPageQuery query) {
        //CourseId和sectionId不能为空
        if (query.getCourseId() == null && query.getSectionId() == null){
            throw new BadRequestException("请求参数不合法");
        }
        //分页查询数据
        Long userId = UserContext.getUser();
        Page<InteractionQuestion> page = this.lambdaQuery()
                //为了提高查询效率，所以这里不查询description字段
                .select(InteractionQuestion.class,q->!"description".equals(q.getProperty()))
                .eq(query.getCourseId() != null, InteractionQuestion::getCourseId, query.getCourseId())
                .eq(query.getSectionId() != null, InteractionQuestion::getSectionId, query.getSectionId())
                .eq(BooleanUtils.isTrue(query.getOnlyMine()), InteractionQuestion::getUserId, userId)
                .eq(InteractionQuestion::getHidden, false)
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = page.getRecords();
        //校验数据是否为空
        if (ObjectUtils.isEmpty(records)){
            return PageDTO.empty(page);
        }
        //根据用户id查询用户的信息
        Set<Long> userIds = records.stream()
                .map(InteractionQuestion::getUserId)
                .collect(Collectors.toSet());


        //获得最新回答的id,根据最新回答的问题id查询查询回答的内容
        Set<Long> answerIds = records.stream()
                .map(InteractionQuestion::getLatestAnswerId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        Map<Long, InteractionReply> answerMap = null;
        if (CollUtils.isNotEmpty(answerIds)){
            List<InteractionReply> answerList = replyService.listByIds(answerIds);
            answerMap = answerList.stream()
                    .collect(Collectors.toMap(InteractionReply::getId, i -> i));
           //根据回答问题的id获得用户的id
            Set<Long> anwserUserId = answerList.stream().map(InteractionReply::getUserId).collect(Collectors.toSet());
            //这里将用户id和最近回答人的id封装在一块
            userIds.addAll(anwserUserId);
        }

        //这里将合并后的用户id，一起查询
        List<UserDTO> userList = userClient.queryUserByIds(userIds);
        Map<Long, UserDTO> userMap = userList.stream()
                .collect(Collectors.toMap(UserDTO::getId, u -> u));

        //转成vo对象
        List<QuestionVO> voList = new ArrayList<>();
        for (InteractionQuestion record : records) {
            QuestionVO vo = BeanUtils.copyBean(record, QuestionVO.class);
            //用户的头像和名称，在匿名的时候不显示
            if (!record.getAnonymity()){
                UserDTO userDTO = userMap.getOrDefault(record.getUserId(), new UserDTO());
                vo.setUserIcon(userDTO.getIcon());
                vo.setUserName(userDTO.getName());
            }
            InteractionReply reply = answerMap.getOrDefault(record.getLatestAnswerId(), new InteractionReply());
            //最新的回答内容
            vo.setLatestReplyContent(reply.getContent());
            //最新的回答用户名称
            if (!reply.getAnonymity()){
                UserDTO userDTO = userMap.getOrDefault(reply.getUserId(), new UserDTO());
                vo.setLatestReplyUser(userDTO.getName());
            }
            voList.add(vo);
        }
        return PageDTO.of(page, voList);
    }

    /**
     * 根据id查询问题详情
     */
    @Override
    public QuestionVO queryQuestionById(Long id) {
        //获得问题详情
        InteractionQuestion question = getById(id);
        if (question == null){
            return null;
        }
        //获得提问者信息
        UserDTO userDTO = null;
        if (!question.getAnonymity()){
             userDTO = userClient.queryUserById(question.getUserId());
        }
        //转成vo对象
        QuestionVO vo = BeanUtils.copyBean(question, QuestionVO.class);
        //确实要判断是否为空
        if (userDTO != null){
            vo.setUserName(userDTO.getName());
            vo.setUserIcon(userDTO.getIcon());
        }
        return vo;
    }


    /**
     * 根据id删除问题以及回答和评论
     * @param id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteQuestionById(Long id) {
        InteractionQuestion question = getById(id);
        //判断问题是否存在
        if (ObjectUtils.isEmpty(question)){
            throw new BadRequestException("问题不存在");
        }
        //判断是否是当前用户提问的问题
        if (ObjectUtils.notEqual(question.getUserId(), UserContext.getUser())) {
            throw new BadRequestException("不能删除他人的问题");
        }
        //删除问题
        deleteQuestionById(id);
        //删除问题下的所有回答以及评论
        boolean result = replyService.lambdaUpdate()
                .eq(InteractionReply::getQuestionId, id)
                .remove();
        if (!result){
            throw new BadRequestException("删除回答及评论失败");
        }
    }


    @Autowired
    private SearchClient searchClient;

    @Autowired
    private CatalogueClient catalogueClient;

    @Autowired
    private CourseClient courseClient;

    @Autowired
    private CategoryCache categoryCache;


    /**
     * 管理端用户分页查询
     * @param query
     * @return
     */
    @Override
    public PageDTO<QuestionAdminVO> queryQuestionPageAdmin(QuestionAdminPageQuery query) {
        //先从es中查询出课程的id，根据课程的id用于分页查询
        List<Long> courseIds = null;
        if (StringUtils.isNotBlank(query.getCourseName())){
            courseIds = searchClient.queryCoursesIdByName(query.getCourseName());
            //如果查到的数据是空的
            if (CollUtils.isEmpty(courseIds)){
                return PageDTO.empty(0L,0L);
            }
        }
        //分页查询问题
        Page<InteractionQuestion> page = this.lambdaQuery()
                .in(CollUtils.isNotEmpty(courseIds), InteractionQuestion::getCourseId, courseIds)
                .eq(query.getStatus() != null, InteractionQuestion::getStatus, query.getStatus())
                .gt(query.getBeginTime() != null, InteractionQuestion::getUpdateTime, query.getBeginTime())
                .lt(query.getEndTime() != null, InteractionQuestion::getUpdateTime, query.getEndTime())
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = page.getRecords();
        if (CollUtils.isEmpty(records)){
            return PageDTO.empty(page);
        }
        Set<Long> userId = new HashSet<>();
        Set<Long> courseId = new HashSet<>();
        Set<Long> cataId = new HashSet<>();
        //循环遍历出所有的id
        for (InteractionQuestion record : records) {
            userId.add(record.getUserId());
            courseId.add(record.getCourseId());
            cataId.add(record.getChapterId());
            cataId.add(record.getSectionId());
        }
        //从用户微服务中获取用户的名称
        List<UserDTO> userList = userClient.queryUserByIds(userId);
        //用户的map
        Map<Long, String> userMap = userList.stream().collect(Collectors.toMap(UserDTO::getId, UserDTO::getName));
        //从课程微服务中获得
        List<CourseSimpleInfoDTO> courseList = courseClient.getSimpleInfoList(courseId);
        //获得课程的信息
        Map<Long, CourseSimpleInfoDTO> courseMap = courseList.stream()
                .collect(Collectors.toMap(CourseSimpleInfoDTO::getId, u -> u));
        //查询章节信息
        List<CataSimpleInfoDTO> cataList = catalogueClient.batchQueryCatalogue(cataId);
        Map<Long, String> cataMap = cataList.stream()
                .collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        //如果不是空的，就准备vo对象，将它返回
        List<QuestionAdminVO> list = new ArrayList<>();
        for (InteractionQuestion record : records) {
            QuestionAdminVO vo = BeanUtils.copyBean(record, QuestionAdminVO.class);
            //用户名字
            vo.setUserName(userMap.get(record.getUserId()));
            CourseSimpleInfoDTO course = courseMap.get(record.getCourseId());
            if (course != null){
                //课程名称
                vo.setCourseName(course.getName());
                //获得三级的id，直接获得它的名称
                String category = categoryCache.getCategoryNames(course.getCategoryIds());
                //三级分类名称
                vo.setCategoryName(category);
            }
            //节名称
            vo.setSectionName(cataMap.get(record.getSectionId()));
            //章名称
            vo.setChapterName(cataMap.get(record.getChapterId()));
            //添加vo
            list.add(vo);
        }
        //返回vo
        return PageDTO.of(page, list);
    }


    /**
     * 管理端隐藏或显示问题
     * @param id
     * @param hidden
     */
    @Override
    public void isHidden(Long id, Boolean hidden) {
        //判断当前是否存在问题
        InteractionQuestion question = getById(id);
        if (question == null){
            throw new BadRequestException("问题不存在");
        }
        //直接更改就行
        boolean result = this.lambdaUpdate().eq(InteractionQuestion::getId, id)
                .set(InteractionQuestion::getHidden, hidden)
                .update();
        if (!result){
            throw new DbRuntimeException("更新数据库失败");
        }
    }


    /**
     * 管理端根据id查询问题详情
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public QuestionAdminVO questionDetailById(Long id) {
        //判断当前的问题是否存在
        InteractionQuestion question = getById(id);
        if (ObjectUtils.isEmpty(question)){
            return null;
        }
        //构建vo对象
        QuestionAdminVO vo = BeanUtils.copyBean(question, QuestionAdminVO.class);
       //获得提问者用户的信息
        UserDTO user = userClient.queryUserById(question.getUserId());
        //设置用户名字
        vo.setUserName(user.getName());
        //设置用户的头像
        vo.setUserIcon(user.getIcon());
        //获得课程信息
        CourseFullInfoDTO courseInfo = courseClient.getCourseInfoById(question.getCourseId(), true, true);
       //根据老师的id查询老师的名称
        List<UserDTO> userDTOS = userClient.queryUserByIds(courseInfo.getTeacherIds());
        //根据课程的三级id获得三级的分类名称
        String name = categoryCache.getCategoryNames(courseInfo.getCategoryIds());
        //根据课程
        vo.setCategoryName(name);
        vo.setCourseName(courseInfo.getName());
        //课程负责老师
        vo.setTeacherName(userDTOS.get(0).getName());
        //将数据库中的状态更改为已查看
        boolean result = this.lambdaUpdate()
                .eq(InteractionQuestion::getId, question.getId())
                .set(InteractionQuestion::getStatus, QuestionStatus.CHECKED.getValue())
                .update();
        if (!result){
            throw new DbException("更新状态失败");
        }
        return vo;
    }
}
